package com.dimples.security.filter;

import com.dimples.security.captcha.ImageCodeHelper;
import com.dimples.security.exception.ValidateCodeException;
import com.dimples.common.properties.DimplesProperties;
import com.dimples.security.handler.DimplesAuthenticationFailureHandler;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;

/**
 * InitializingBean: 将会在spring初始化bean时会调用, afterPropertiesSet 可以为bean设置初始化参数
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/6/26
 */
@SuppressWarnings("NullableProblems")
@Configuration
@RequiredArgsConstructor
public class DimplesImageCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private final Set<String> url = CollUtil.newHashSet();
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    private final ImageCodeHelper imageCodeHelper;
    private final DimplesProperties properties;
    private final DimplesAuthenticationFailureHandler failureHandler;

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        url.add(properties.getCaptcha().getLoginProcessingUrl());
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        boolean match = false;
        for (String u : url) {
            if (pathMatcher.match(u, request.getRequestURI())) {
                match = true;
            }
        }
        if (match) {
            try {
                imageCodeHelper.validateCode(request);
            } catch (ValidateCodeException e) {
                failureHandler.onAuthenticationFailure(request, response, e);
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}
